home *** CD-ROM | disk | FTP | other *** search
/ Pascal Super Library / Pascal Super Library (CW International)(1997).bin / LIBRARY / PCTV3N5 / FPNUM.H < prev    next >
C/C++ Source or Header  |  1992-09-20  |  7KB  |  160 lines

  1. /*==================================================================
  2.  fpnum.h -- Fixed point math class header  [Listing #1]
  3.  by Robert N. Goldrich
  4.  Tested with Borland, Microsoft, Zortech, and TopSpeed C++
  5. ==================================================================*/
  6. #include <iostream.h>       // for stream operators
  7.  
  8. /*------------------------------------------------------------------
  9.  fpnum class
  10. ------------------------------------------------------------------*/
  11. #define sizeof_long      4  // sizeof not allowed in preprocessor
  12. #define sizeof_int       2  // .. so have to do this manually
  13. #define FP_FRCBITS      16  // number of fraction bits
  14. #define FP_TOTBITS      ( sizeof_long *8  )   // bits in a 'long'
  15.  
  16. #if( (FP_FRCBITS >= FP_TOTBITS-1) || (FP_FRCBITS < sizeof_int*8) )
  17.     #error (fpnum.h) Too many or too few decimal bits in fpnum.
  18. #endif
  19.  
  20. #define FP_ONE          ( 1L << FP_FRCBITS )
  21. #define FP_HALF         ( FP_ONE >> 1 )
  22. #define FP_MIN          ( 1L << ( FP_TOTBITS-1 ) )      // 8000 0000
  23. #define FP_MAX          ( ~FP_MIN )                     // 7fff ffff
  24. #define FP_ALLBITS      ( ~0L )                         // ffff ffff
  25. #define FP_MAXDECPL     ( ((FP_TOTBITS-1)*301) / 1000 - 1 )
  26.     // 301 = log(2) the maximum # of decimal places shown on output
  27.  
  28. class fpnum {
  29.     long    xx ;
  30.     fpnum( long a ) { xx = a ; } ;
  31.     /*--
  32.     A *private* constructor which just stuffs a long value into xx.
  33.     Dangerous if public and not needed publicly because generally,
  34.     a long is too large to store in a fpnum.  Use poke() instead.
  35.     --*/
  36.  
  37. public:
  38.  
  39. //--constructors
  40.     fpnum() { xx = 0 ; } ;
  41.     fpnum( int a ) { xx = (long)a << FP_FRCBITS ; } ;
  42.     fpnum( int a, int b ) { *this = fpnum(a) / fpnum(b) ; } ;
  43.     fpnum( char *str ) { *this = atofp( str ) ; } ;
  44.  
  45. //--simple assignment method
  46. //  The following assignment operator is generated automatically for
  47. //  every class.  It can, however be overridden.
  48. //  fpnum& operator=( const fpnum& a ) { xx = a.xx; return *this;} ;
  49.  
  50. //--binary operators: fpnum (operator) fpnum
  51.     friend fpnum  operator+( const fpnum& a, const fpnum& b ) {
  52.             return fpnum( a.xx + b.xx ) ; } ;
  53.     friend fpnum  operator-( const fpnum& a, const fpnum& b ) {
  54.             return fpnum( a.xx - b.xx ) ; } ;
  55.     friend fpnum  operator*( const fpnum& a, const fpnum& b ) ;
  56.     friend fpnum  operator/( const fpnum& a, const fpnum& b ) ;
  57.     friend fpnum  operator%( const fpnum& a, const fpnum& b ) {
  58.             return fpnum( a.xx % b.xx ) ; } ;
  59.  
  60. //--binary operators: fpnum * int
  61.     /*---
  62.     The following two methods are included to enhance performance,
  63.     and are really not needed from a language point of view.
  64.     Multiplication of fpnums with integers could be handled without
  65.     them as follows:
  66.         1. the int will be promoted to a fpnum via the constructor
  67.            conversion
  68.         2. the fpnum * fpnum function will be called
  69.     These operators perform the same function much more efficiently.
  70.     ---*/
  71.     friend fpnum  operator*( const fpnum& a, int b ) {
  72.             return fpnum( a.xx * b ) ; } ;
  73.     friend fpnum  operator*( int a, const fpnum& b ) {
  74.             return fpnum( b.xx * a ) ; } ;
  75.  
  76. //--assignment operators
  77.     fpnum& operator+=( const fpnum& a ) {
  78.                 xx += a.xx ;  return *this ; } ;
  79.     fpnum& operator-=( const fpnum& a ) {
  80.                 xx -= a.xx ;  return *this ; } ;
  81.     fpnum& operator*=( const fpnum& a ) {
  82.                 *this = *this * a ;  return *this ; } ;
  83.     fpnum& operator/=( const fpnum& a ) {
  84.                 *this = *this / a ;  return *this ; } ;
  85.     fpnum& operator%=( const fpnum& a ) {
  86.                 *this = *this % a ;  return *this ; } ;
  87.  
  88. //--increment/decrement operators
  89.     // pre- operators return reference to self after incrementing
  90.     fpnum& operator++() { xx += FP_ONE; return *this; } ;
  91.     fpnum& operator--() { xx -= FP_ONE; return *this; } ;
  92.  
  93.     // post- operators return value of original fpnum
  94.     fpnum  operator++( int ) {
  95.         long yy = xx ;  xx += FP_ONE ;  return fpnum( yy ) ; } ;
  96.     fpnum  operator--( int ) {
  97.         long yy = xx ;  xx -= FP_ONE ;  return fpnum( yy ) ; } ;
  98.  
  99. //--unary operators
  100. //  Zortech doesn't like the unary + operator for some reason
  101.     fpnum  operator+() const { return *this ; } ;
  102.     fpnum  operator-() const { return fpnum( -xx ) ; }
  103.  
  104. //--type conversion methods
  105.     friend int round_to_int( const fpnum& a ) ;
  106.     friend int trunc_to_int( const fpnum& a ) ;
  107.  
  108. //--logical operators
  109.     friend int operator<( const fpnum& a, const fpnum& b ) {
  110.             return ( a.xx < b.xx ) ; } ;
  111.     friend int operator<=( const fpnum& a, const fpnum& b ) {
  112.             return ( a.xx <= b.xx ) ; } ;
  113.     friend int operator==( const fpnum& a, const fpnum& b ) {
  114.             return ( a.xx == b.xx ) ; } ;
  115.     friend int operator>=( const fpnum& a, const fpnum& b ) {
  116.             return ( a.xx >= b.xx ) ; } ;
  117.     friend int operator>( const fpnum& a, const fpnum& b ) {
  118.             return ( a.xx > b.xx ) ; } ;
  119.     friend int operator!=( const fpnum& a, const fpnum& b ) {
  120.             return ( a.xx != b.xx ) ; } ;
  121.  
  122. //--trig functions
  123.     friend fpnum fp_sin( int angle ) ;
  124.     friend fpnum fp_cos( int angle ) { return fp_sin( 90+angle ); };
  125.     friend fpnum fp_tan( int angle ) ;
  126.  
  127. //--conversions between fpnums and strings / stream operators
  128.     friend fpnum atofp( char *str ) ;
  129.     friend char *fptoa( const fpnum& n, char *str ) ;
  130.     friend ostream& operator<<( ostream& o, const fpnum& n ) ;
  131.     friend istream& operator>>( istream& i, const fpnum& n ) ;
  132.  
  133. //--odds and ends
  134.     fpnum& poke( long a ) { xx = a ;  return *this ; } ;
  135.     long   peek() const { return xx ; } ;
  136.     fpnum& inc_by( long a ) {   // might want this in a pinch
  137.             xx += a ; return *this ; } ;
  138.  
  139.     fpnum& change_sign() {      // much more efficient than  fp= -fp
  140.             xx = -xx ; return *this ; } ;
  141.     friend fpnum  fpabs( fpnum a ) {
  142.             return  fpnum( (a.xx < 0 ? -a.xx : a.xx ) ) ; } ;
  143.     friend int signof( fpnum a ) {
  144.             return  a.xx < 0 ? -1 : 1 ; } ;
  145.  
  146. //--fpnum constants
  147. #if 0
  148. // Borland, Zortech, and TopSpeed do not allow these constants to be
  149. // initialized with the private constructor, though they should.
  150. static const fpnum  fp_max,     // maximum fpnum
  151.                     fp_min,     // minimum fpnum
  152.                     fp_res ;    // fpnum resolution
  153. #endif
  154. } ;
  155.  
  156.  
  157.  
  158.  
  159.  
  160.